
#include "container/container-impl.h"
#include "common/logger.h"
#include "common/module-logger.h"
#include "fiber-env/fiber-env.h"
#include "net-server/fcgi-server.h"

#include <signal.h>
#include <unistd.h>
#include <memory>

static bool quit_flag = false;

typedef fasmio::net_server::FcgiServer      NetServer;
typedef fasmio::container::ContainerImpl    Container;
typedef fasmio::common::Logger              Logger;

void sigint_handler(int)
{
    quit_flag = true;
}

int fiber_main(int argc, char* argv[])
{
    sighandler_t handler = signal(SIGINT, sigint_handler);

    std::unique_ptr<fasmio::ILogger> logger(new Logger());
    fasmio::common::ModuleLogger mlogger(logger.get(), "main");
    mlogger.Info("Starting server ...");

    std::unique_ptr<fasmio::IContainer> container(new Container(logger.get()));
    if (!container->Initialize())
    {
        mlogger.Error("Failed to initialize container");
        return 1;
    }

    std::unique_ptr<fasmio::INetServer> net_server(new NetServer(logger.get()));
    if (!net_server->Start(container.get()))
    {
        mlogger.Error("Failed to start net-server");
        return 1;
    }

    mlogger.Info("Server started");

    while (!quit_flag)
        fasmio::fiber_env::Sleep(10);
    signal(SIGINT, handler);

    mlogger.Info("Stopping server ...");

    net_server->Stop();
    net_server.reset();

    container->Finalize();
    container.reset();

    mlogger.Info("Server stopped");
    logger.reset();
    return 0;
}


struct command_line_args_t
{
    int argc;
    char** argv;
};

int fiber_main_wrap(void* arg)
{
    command_line_args_t *args = reinterpret_cast<command_line_args_t*>(arg);

    int result = fiber_main(args->argc, args->argv);
    fasmio::fiber_env::NotifyToStop();
    return result;
}

int main(int argc, char* argv[])
{
    command_line_args_t args;
    args.argc = argc;
    args.argv = argv;

    std::unique_ptr<fasmio::fiber_env::FiberEnv> env(fasmio::fiber_env::NewFiberEnv());
    if (!env->Start())
        return 1;

    fasmio::fiber_env::Fiber* fiber = env->CreateFiber(fiber_main_wrap, &args, "fiber-main");
    if (fiber == 0)
        return 1;
    if (!env->FiberizeThisThread())
        return 1;

    env->Stop();
    return 0;
}

